package com.dalimao.library;

import com.dalimao.library.util.BignessUtil;
import com.dalimao.library.util.LogUtil;
import com.dalimao.library.util.TypeFlag;
import com.dalimao.library.util.WindowInfo;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.utils.Point;
import ohos.agp.utils.Rect;
import ohos.agp.window.service.Window;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;

/**
 * FloatUtil
 *
 * @since 2021-06-28
 */
public class FloatUtil {
    private static final int DURATIONVALUE = 300;

    private static final int PIXELFORMATVALUE = -3;

    // 状态栏高度
    private static final int BARTITLE = 120;

    // 导航栏偏移量
    private static final int NAVIGATIONBAROFFSET = 100;

    // 窗体界面
    private Component view;

    // 对其方式
    private int gravity;

    // 窗体高度
    private int height;

    // 窗体宽度
    private int width;

    // 是否可以移动
    private boolean mIsMovable;

    // 窗体层级
    private TypeFlag typeFlag;

    // 坐标
    private Point point;
    private Context mContext;
    private Window window;
    private WindowManager windowManager;

    private FloatUtil(FloatUtil.Builder builder, Context context) {
        this.mContext = context;
        this.view = builder.mView;
        this.gravity = builder.mGravity;
        this.height = builder.mHeight;
        this.width = builder.mWidth;
        this.mIsMovable = builder.mIsMovable;
        this.typeFlag = builder.mTypeFlag;
        this.point = builder.mPoint;
        showView();
    }

    /**
     * 弹窗布局
     *
     * @return Component
     */
    public Component getView() {
        return view;
    }

    /**
     * 弹窗布局
     *
     * @param view
     */
    public void setView(Component view) {
        this.view = view;
    }

    /**
     * 对其方式
     *
     * @return int
     */
    public int getGravity() {
        return gravity;
    }

    /**
     * 对其方式
     *
     * @param gravity
     */
    public void setGravity(int gravity) {
        this.gravity = gravity;
    }

    /**
     * 窗口高度
     *
     * @return int
     */
    public int getHeight() {
        return height;
    }

    /**
     * 窗口高度
     *
     * @param height 高度
     */
    public void setHeight(int height) {
        this.height = height;
    }

    /**
     * 窗口宽度
     *
     * @return int
     */
    public int getWidth() {
        return width;
    }

    /**
     * 窗口宽度
     *
     * @param width 宽度
     */
    public void setWidth(int width) {
        this.width = width;
    }

    /**
     * 是否可以移动
     *
     * @return boolean
     */
    public boolean isMovable() {
        return mIsMovable;
    }

    /**
     * 是否可以移动
     *
     * @param isMovable
     */
    public void setmIsMovable(boolean isMovable) {
        this.mIsMovable = isMovable;
    }

    /**
     * 弹窗层级
     *
     * @return TypeFlag
     */
    public TypeFlag getTypeFlag() {
        return typeFlag;
    }

    /**
     * 弹窗层级
     *
     * @param typeFlag
     */
    public void setTypeFlag(TypeFlag typeFlag) {
        this.typeFlag = typeFlag;
    }

    /**
     * 指定x,y位置
     *
     * @return Point
     */
    public Point getPoint() {
        return point;
    }

    /**
     * 指定x,y位置
     *
     * @param point
     */
    public void setPoint(Point point) {
        this.point = point;
    }

    /**
     * Builder
     *
     * @since 2021-06-28
     */
    public static class Builder {
        private static final int WINDOWDEFAULTHEIGHT = 250;
        private static final int WINDOWDEFAULTWIDTH = 230;

        // 窗体界面
        private Component mView;

        // 对其方式
        private int mGravity = LayoutAlignment.LEFT | LayoutAlignment.TOP;

        // 窗体高度
        private int mHeight = WINDOWDEFAULTHEIGHT;

        // 窗体宽度
        private int mWidth = WINDOWDEFAULTWIDTH;

        // 是否可以移动
        private boolean mIsMovable = false;

        // 窗体层级
        private TypeFlag mTypeFlag = TypeFlag.MOD_APP_OVERLAY;

        // 坐标
        private Point mPoint;

        /**
         * Component
         *
         * @param view
         * @return FloatUtil.Builder
         */
        public FloatUtil.Builder setComponent(Component view) {
            this.mView = view;
            return this;
        }

        /**
         * Gravity
         *
         * @param gravity
         * @return FloatUtil.Builder
         */
        public FloatUtil.Builder setGravity(int gravity) {
            this.mGravity = gravity;
            return this;
        }

        /**
         * height
         *
         * @param height
         * @return FloatUtil.Builder
         */
        public FloatUtil.Builder setHeight(int height) {
            this.mHeight = height;
            return this;
        }

        /**
         * width
         *
         * @param width
         * @return FloatUtil.Builder
         */
        public FloatUtil.Builder setWidth(int width) {
            this.mWidth = width;
            return this;
        }

        /**
         * mIsMovable
         *
         * @param isMovable
         * @return FloatUtil.Builder
         */
        public FloatUtil.Builder setIsMovable(boolean isMovable) {
            this.mIsMovable = isMovable;
            return this;
        }

        /**
         * typeFlag
         *
         * @param typeFlag
         * @return FloatUtil.Builder
         */
        public FloatUtil.Builder setTypeFlag(TypeFlag typeFlag) {
            this.mTypeFlag = typeFlag;
            return this;
        }

        /**
         * point
         *
         * @param point
         * @return FloatUtil.Builder
         */
        public FloatUtil.Builder point(Point point) {
            this.mPoint = point;
            return this;
        }

        /**
         * build
         *
         * @param context
         * @return FloatUtil
         */
        public FloatUtil showFloatView(Context context) {
            return new FloatUtil(this, context);
        }
    }

    /**
     * showView
     */
    public void showView() {
        windowManager = WindowManager.getInstance();
        String className = view.getClass().getName();
        WindowInfo windowInfo = new WindowInfo();
        windowInfo.setClassName(className);
        hideView(BignessUtil.isExistComponent(windowInfo));
        BignessUtil.deleteExistComponent(windowInfo);

        // WindowManager.LayoutConfig.MOD_APPLICATION_OVERLAY 悬浮于应用之上没有传递事件
        // WindowManager.LayoutConfig.MOD_APPLICATION 应用内
        window = WindowManager.getInstance().addComponent((ComponentContainer) view, mContext, setTypeWindow(typeFlag));
        window.setMovable(mIsMovable);
        window.setTransparent(true);

        windowInfo.setWindow(window);
        BignessUtil.setInstanceComponent(windowInfo);

        WindowManager.LayoutConfig layoutConfig1 = new WindowManager.LayoutConfig();

        layoutConfig1.width = AttrHelper.vp2px(width, mContext);
        layoutConfig1.height = AttrHelper.vp2px(height, mContext);
        layoutConfig1.alignment = gravity;
        layoutConfig1.flags = WindowManager.LayoutConfig.INPUT_ADJUST_PAN;
        layoutConfig1.pixelFormat = PIXELFORMATVALUE;

        // 设置窗口的xy坐标
        if (point != null) {
            layoutConfig1.x = point.getPointXToInt();
            layoutConfig1.y = point.getPointYToInt();
        }

        Rect rect = new Rect();
        rect.top = BignessUtil.getStatusBarHeight(mContext) - BARTITLE;
        rect.left = 0;
        rect.right = BignessUtil.getScreenPiex(mContext).width;
        rect.bottom = BignessUtil.getScreenPiex(mContext).height + NAVIGATIONBAROFFSET;

        window.setBoundRect(rect);
        window.setLayoutConfig(layoutConfig1);
        view.setScale(0f, 0f);
        AnimatorValue animatorValue = setAnimator();
        animatorValue.setValueUpdateListener((animatorValue1, v) -> {
            view.setScale(v, v);
        });
        animatorValue.start();

        window.setLayoutConfig(layoutConfig1);
    }

    private AnimatorValue setAnimator() {
        AnimatorValue animatorValue = new AnimatorValue();
        animatorValue.setDuration(DURATIONVALUE);
        return animatorValue;
    }

    /**
     * 关闭窗体
     *
     * @param componentView
     */
    public void hideFloatView(Component componentView) {
        WindowInfo windowInfo = new WindowInfo();
        windowInfo.setClassName(componentView.getClass().getName());
        windowInfo = BignessUtil.isExistComponent(windowInfo);
        if (BignessUtil.isExistComponent(windowInfo) != null) {
            WindowInfo windowInfo1 = BignessUtil.isExistComponent(windowInfo);
            view.setScale(1f, 1f);
            AnimatorValue animatorValue = setAnimator();
            animatorValue.setValueUpdateListener((animatorValue1, v) -> {
                view.setScale(1 - v, 1 - v);
            });

            animatorValue.setStateChangedListener(new Animator.StateChangedListener() {
                @Override
                public void onStart(Animator animator) {
                }

                @Override
                public void onStop(Animator animator) {
                }

                @Override
                public void onCancel(Animator animator) {
                    hideView(windowInfo1);
                }

                @Override
                public void onEnd(Animator animator) {
                    hideView(windowInfo1);
                }

                @Override
                public void onPause(Animator animator) {
                }

                @Override
                public void onResume(Animator animator) {
                }
            });

            animatorValue.start();
        }
    }

    /**
     * hideView
     *
     * @param info
     */
    private void hideView(WindowInfo info) {
        if (info != null) {
            if (info.getWindow() != null && windowManager != null) {
                try {
                    windowManager.destroyWindow(info.getWindow());
                } catch (Exception e) {
                    LogUtil.error("hideView", "Exception");
                }
            }
            BignessUtil.deleteExistComponent(info);
        }
    }

    /**
     * 窗体的显示层级
     *
     * @param enuTypeFlag
     * @return int
     */
    private int setTypeWindow(TypeFlag enuTypeFlag) {
        int windowFlag;
        if (enuTypeFlag == TypeFlag.MOD_APP_OVERLAY) {
            windowFlag = WindowManager.LayoutConfig.MOD_APPLICATION_OVERLAY;
        } else {
            windowFlag = WindowManager.LayoutConfig.INPUT_ADJUST_PAN;
        }
        return windowFlag;
    }
}
